package fi.foyt.jabberd2json.demo;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;

import fi.foyt.jabberd2json.Filter;
import fi.foyt.jabberd2json.ObjectSet;
import fi.foyt.jabberd2json.ObjectSetField;
import fi.foyt.jabberd2json.ObjectSetHandler;
import fi.foyt.jabberd2json.ObjectSetType;
import fi.foyt.jabberd2json.ObjectSetUpdateMode;

import net.sf.json.JSONObject;

/**
 * This is a demo servlet for jabberd2-json-lib-java. 
 * 
 * It shows how to create a servlet for the jabberd2-json-driver but does not really 
 * return or store any data, so don't expect it to do anything without modifications.      
 */
public class DemoServlet extends HttpServlet {

  private static final long serialVersionUID = 1L;

  @Override
  protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    JSONObject responseObject = new JSONObject();

    try {
      if (req.getRequestURI().endsWith("get.json"))
        handleGet(req, resp, responseObject);
      else if (req.getRequestURI().endsWith("set.json"))
        handleSet(req, resp, responseObject);
      else {
        throw new RuntimeException("Illegal request");
      }

      responseObject.put("statusCode", 0);
    } catch (Exception e) {
      responseObject.put("statusCode", 1);
      responseObject.put("errorMessage", e.toString());
    } finally {
      PrintWriter responseWriter = resp.getWriter();
      try {
        resp.setContentType("text/javascript");
        responseObject.write(responseWriter);
      } finally {
        responseWriter.close();
      }
    }
  }

  private void handleGet(HttpServletRequest req, HttpServletResponse resp, JSONObject responseObject) {
    String typeParam = req.getParameter("type");
    String ownerParam = req.getParameter("owner");
    String filterParam = req.getParameter("filter");

    ObjectSetHandler handler = getObjectSetHandler(typeParam);
    if (handler == null)
      throw new RuntimeException("Unknown ObjectSetType: " + typeParam);

    List<List<JSONObject>> jsonSets = new ArrayList<List<JSONObject>>();

    Filter filter = null;
    if (!StringUtils.isBlank(filterParam)) {
      filter = Filter.parseFromString(filterParam);
    }

    List<ObjectSet> objectSets = handler.readObjectSets(ownerParam, filter);
    for (ObjectSet objectSet : objectSets) {
      List<JSONObject> jsonFields = new ArrayList<JSONObject>();

      for (ObjectSetField field : objectSet.getFields()) {
        JSONObject fieldObject = new JSONObject();
        fieldObject.put("type", field.getType());
        fieldObject.put("key", field.getKey());
        fieldObject.put("value", field.getValue());
        jsonFields.add(fieldObject);
      }

      jsonSets.add(jsonFields);
    }

    responseObject.put("sets", jsonSets);
  }

  private void handleSet(HttpServletRequest req, HttpServletResponse resp, JSONObject responseObject) {
    String typeParam = req.getParameter("type");
    String ownerParam = req.getParameter("owner");
    String filterParam = req.getParameter("filter");
    String modeParam = req.getParameter("mode");
    
    ObjectSetHandler handler = getObjectSetHandler(typeParam);
    if (handler == null)
      throw new RuntimeException("Unknown ObjectSetType: " + typeParam);
        
    Filter filter = null;
    if (!StringUtils.isBlank(filterParam)) {
      filter = Filter.parseFromString(filterParam);
    }
        
    ObjectSetUpdateMode updateMode = ObjectSetUpdateMode.getByName(modeParam);
    
    Map<String, String> values = new HashMap<String, String>();
    
    for (Object key : req.getParameterMap().keySet()) {
      if (!reservedParams.contains(key)) {
        String[] paramValues = req.getParameterMap().get(key);
        if (paramValues.length == 1)
          values.put((String) key, paramValues[0]);
      }
    }
        
    handler.updateObjectSet(ownerParam, filter, updateMode, values);
  }

  private ObjectSetHandler getObjectSetHandler(String type) {
    ObjectSetType objectSetType = ObjectSetType.getByName(type);

    switch (objectSetType) {
      case STATUS:
        return new StatusObjectSetHandler();
    }

    return null;
  }
  
  private static Set<String> reservedParams = new HashSet<String>();
  
  static {
    reservedParams.add("type");
    reservedParams.add("owner");
    reservedParams.add("filter");
    reservedParams.add("mode");
  }
}
